using System;
using System.Collections.Generic;
using System.Text;
using Decav.Gatsb.Mobile;
using Decav.Gatsb.Data;
using System.IO;
using Decav.Gatsb.Configuration;
using Decav.Gatsb.Application.Configuration;
using Decav.Diagnostics;
using System.Diagnostics;

namespace Decav.Gatsb.Application
{
    /// <summary>
    /// Reads messages from a <see cref="MessageListener"/>, parses them and performs actions against a <see cref="GatsbApplication"/>
    /// instance.
    /// </summary>
    public class MessageService
    {
        public MessageService()
        {
            _parser = new MessageParser();
            _listener = new MessageListener(GatsbApplicationConfigurationSection.Current.MailDropPath);

            _listener.MessageReceived += new EventHandler<MessageReceivedEventArgs>(Listener_MessageReceived);
        }

        private MessageParser _parser;
        private MessageListener _listener;
        private CommandInterpreter _interpreter = new CommandInterpreter();
        private bool _running;
        private readonly object _syncRoot = new object();

        void Listener_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            ProcessMessage(e.FileName);
        }

        private void ProcessMessage(string fileName)
        {
            if (!_running)
                throw new InvalidOperationException("Cannot parse a message when the service is not running.");

            try
            {
                MobileMessage message = _parser.Parse(fileName);



                ExecuteCommand(message);
            }
            catch(Exception ex)
            {
                Debugger.Break();

                // If its just junk mail, then delete it and move on.
                if (ex is MessageSenderInvalidException)
                {
                    File.Delete(fileName);
                    return;
                }
                
                File.WriteAllText(
                    Path.Combine(GatsbApplicationConfigurationSection.Current.BadMailPath,
                    string.Format("{0}.log", Path.GetFileNameWithoutExtension(fileName))),
                    DecavDiagnostics.GetExceptionDetails(ex));

                // Swallow the exception and throw the mail into a bad mail path, 
                // so it can be manually parsed or reviewed later.
                try
                {
                    File.Move(fileName,
                        Path.Combine(GatsbApplicationConfigurationSection.Current.BadMailPath,
                        Path.GetFileName(fileName)));
                }
                catch { /* swallow exception and we'll try again */ }
            }

            File.Delete(fileName); // Clean up the file so its not reprocessed
        }

        private void ExecuteCommand(MobileMessage message)
        {
            _interpreter.Execute(message);
        }

        /// <summary>
        /// Begins listening to a <see cref="MessageListener"/> and parsing messages.
        /// </summary>
        public void Start()
        {
            lock (_syncRoot)
            {
                if (_running)
                    throw new InvalidOperationException("The MessageService is already started.");

                _listener.Start();
                _running = true;
            }
        }

        /// <summary>
        /// Ends the listening for new messages and stops parsing messages.
        /// </summary>
        public void Stop()
        {
            lock (_syncRoot)
            {
                if (!_running)
                    return;

                _listener.Stop();
                _listener.Dispose();
                _running = false;
            }
        }
    }
}
